/*
** client.c for  in /home/renard/Dropbox/epitech/dev/projets/systemunix/zappy/zappy-2015-2014s-renard_g/serv-src
**
** Made by guillaume renard
** Login   <renard_g@epitech.net>
**
** Started on  Thu Jun 21 15:57:47 2012 guillaume renard
** Last update Thu Jul 19 18:14:48 2012 pierrick druart
*/

#include		<stdio.h>
#include		<stdlib.h>
#include		<string.h>

#include		"server.h"

static const char	*func[]=
{
  "avance",
  "droite",
  "gauche",
  "voir",
  "inventaire",
  "pose",
  "prend",
  "fork",
  "connect_nbr",
  "incantation",
  "broadcast",
  "expulse",
  NULL
};

static void		write_client(struct s_client *client, t_game *game)
{
  unsigned int		tot;
  unsigned int		len;
  int			ret;

  tot = 0;
  len = strlen(client->send->str);
  while (tot != len)
  {
    if ((ret = write(client->sock, client->send->str, len)) != -1)
      tot += ret;
  }
  if (!strcmp("mort\n", client->send->str))
  {
    game->obj[client->gamer->coord.y][client->gamer->coord.x].inv[JOUEUR]--;
    if (client->gamer->level == 8)
      client->gamer->team->nb_maxlvl--;
    client->gamer->team->check_slot(client->gamer->team, game->nb_player);
    client->gamer->task->clear(client->gamer->task, NULL);
    free(client->gamer->task);
    free(client->gamer);
    client->gamer = NULL;
  }
  client->send->clear(client->send);
}

static t_item		*check_team(t_game *game, t_client *client,
    const char *str, t_item *item)
{
  struct s_item		*cur;
  struct s_team		*team;

  cur = game->team->head;
  while (cur != NULL)
  {
    team = (struct s_team *)cur->content;
    if (!strcmp(team->name, str))
    {
      if (team->egg->len > 0)
	check_team_egg_slot(client, team, game);
      else if (team->slot > 0)
	check_team_slot(client, team, game);
      return (item->next);
    }
    cur = cur->next;
  }
  return (item);
}

static void		check_cmd(char *cmd, t_client *client, t_game *game,
    t_item **cur)
{
  char			*str;
  int			i;

  if (client->gamer != NULL)
  {
    i = 0;
    if (client->gamer->task->len < 10)
      while (func[i] != NULL)
      {
	if (!strncmp(func[i], cmd, strlen(func[i])))
	{
	  str = strdup(cmd);
	  client->gamer->task->add_back(client->gamer->task, (void *)str);
	  break;
	}
	i++;
      }
  }
  else if (game->graphic != NULL && client == game->graphic)
    cmd_monitor(cmd, client, game);
  else if (game->graphic == NULL && !strcmp(cmd, "GRAPHIC"))
    check_team_graph(game, client);
  else if (client->gamer == NULL)
    *cur = check_team(game, client, cmd, *cur);
}

static void		read_client(t_list *clients, t_client *client,
    t_item **cur, t_game *game)
{
  int			ret;
  char			data[256];
  char			*ptr;

  ret = xread(client->sock, data, 255);
  if (ret == -1)
    *cur = kill_client(clients, client, game, *cur);
  else if (!ret)
    *cur = kill_client(clients, client, game, *cur);
  if (ret > 0)
  {
    data[ret] = 0;
    client->rcv->concat(client->rcv, data);
    if ((ptr = strtok(client->rcv->str, "\n")) != NULL)
    {
      while (ptr != NULL)
      {
	check_cmd(ptr, client, game, cur);
	ptr = strtok(NULL, "\n");
      }
      client->rcv->clear(client->rcv);
    }
  }
}

void			check_client(t_list *clients, t_fd *fds, t_game *game,
    long unsigned int elapsed_time)
{
  struct s_client	*client;
  struct s_item		*cur;

  cur = clients->head;
  while (cur != NULL)
  {
    client = (struct s_client *)cur->content;
    if (FD_ISSET(client->sock, &(fds->rfds)))
      read_client(clients, client, &cur, game);
    else if (client->send->size > 0 && FD_ISSET(client->sock, &(fds->wfds)))
      write_client(client, game);
    if (cur != NULL)
    {
      client = (struct s_client *)cur->content;
      if (client->sock > (int)game->maxfd)
	game->maxfd = client->sock;
      client = (struct s_client *)cur->content;
      if (client->gamer && check_food(game, client, elapsed_time))
	play(client, game, elapsed_time);
      cur = cur->next;
    }
  }
}
